﻿# -*- coding: UTF-8 -*-   

import os
import ahocorasick

class QuestionClassifier:
    def __init__(self):
        # 获取当前文件的绝对路径
        cur_dir = os.path.dirname(os.path.abspath(__file__))
        # 获取项目根目录
        project_root = os.path.dirname(cur_dir)
        # 构建特征词目录的绝对路径
        resource_dir = os.path.join(project_root, 'resource', 'data', '特征词')
        
        # 打印路径以便调试
        print(f"特征词目录路径: {resource_dir}")
        
        #　特征词路径
        self.kecheng_path = os.path.join(resource_dir, 'kecheng.txt')
        self.kechengJX_path = os.path.join(resource_dir, 'kechengJX.txt')
        self.kechengNX_path = os.path.join(resource_dir, 'kechengNX.txt')
        self.kechengZSD_path = os.path.join(resource_dir, 'kechengZSD.txt')
        self.kechengZSDJX_path = os.path.join(resource_dir, 'kechengZSDJX.txt')
        self.kechengZSDNX_path = os.path.join(resource_dir, 'kechengZSDNX.txt')
        self.kechengZSDY_path = os.path.join(resource_dir, 'kechengZSDY.txt')
        self.kechengZSDYJX_path = os.path.join(resource_dir, 'kechengZSDYJX.txt')
        self.kechengZSDYNX_path = os.path.join(resource_dir, 'kechengZSDYNX.txt')
        self.xiti_path = os.path.join(resource_dir, 'xiti.txt')
        self.zhuanye_path = os.path.join(resource_dir, 'zhuanye.txt')
        self.zhuanyeJX_path = os.path.join(resource_dir, 'zhuanyeJX.txt')
        self.ZSD_path = os.path.join(resource_dir, 'ZSD.txt')
        self.ZSDJX_path = os.path.join(resource_dir, 'ZSDJX.txt')
        self.ZSDNX_path = os.path.join(resource_dir, 'ZSDNX.txt')
        self.ZSDY_path = os.path.join(resource_dir, 'ZSDY.txt')
        self.ZSDYJX_path = os.path.join(resource_dir, 'ZSDYJX.txt')
        self.ZSDYNX_path = os.path.join(resource_dir, 'ZSDYNX.txt')

        # 加载特征词
        self.kecheng_wds= [i.strip() for i in open(self.kecheng_path,encoding="ANSI") if i.strip()]
        self.kechengJX_wds= [i.strip() for i in open(self.kechengJX_path,encoding="ANSI") if i.strip()]
        self.kechengNX_wds= [i.strip() for i in open(self.kechengNX_path,encoding="ANSI") if i.strip()]
        self.kechengZSD_wds= [i.strip() for i in open(self.kechengZSD_path,encoding="ANSI") if i.strip()]
        self.kechengZSDJX_wds= [i.strip() for i in open(self.kechengZSDJX_path,encoding="ANSI") if i.strip()]
        self.kechengZSDNX_wds= [i.strip() for i in open(self.kechengZSDNX_path,encoding="ANSI") if i.strip()]
        self.kechengZSDY_wds = [i.strip() for i in open(self.kechengZSDY_path, encoding="ANSI") if i.strip()]
        self.kechengZSDYJX_wds = [i.strip() for i in open(self.kechengZSDYJX_path, encoding="ANSI") if i.strip()]
        self.kechengZSDYNX_wds = [i.strip() for i in open(self.kechengZSDYNX_path, encoding="ANSI") if i.strip()]
        self.xiti_wds = [i.strip() for i in open(self.xiti_path, encoding="ANSI") if i.strip()]
        self.zhuanye_wds = [i.strip() for i in open(self.zhuanye_path, encoding="ANSI") if i.strip()]
        self.zhuanyeJX_wds = [i.strip() for i in open(self.zhuanyeJX_path, encoding="ANSI") if i.strip()]
        self.ZSD_wds = [i.strip() for i in open(self.ZSD_path, encoding="ANSI") if i.strip()]
        self.ZSDJX_wds = [i.strip() for i in open(self.ZSDJX_path, encoding="ANSI") if i.strip()]
        self.ZSDNX_wds = [i.strip() for i in open(self.ZSDNX_path, encoding="ANSI") if i.strip()]
        self.ZSDY_wds = [i.strip() for i in open(self.ZSDY_path, encoding="ANSI") if i.strip()]
        self.ZSDYJX_wds = [i.strip() for i in open(self.ZSDYJX_path, encoding="ANSI") if i.strip()]
        self.ZSDYNX_wds = [i.strip() for i in open(self.ZSDYNX_path, encoding="ANSI") if i.strip()]

        self.region_words = set(
            self.kecheng_wds + self.kechengJX_wds + self.kechengNX_wds + self.kechengZSD_wds + 
            self.kechengZSDJX_wds + self.kechengZSDNX_wds + self.kechengZSDY_wds + 
            self.kechengZSDYJX_wds + self.kechengZSDYNX_wds + self.xiti_wds + self.zhuanye_wds + 
            self.zhuanyeJX_wds + self.ZSD_wds + self.ZSDJX_wds + self.ZSDNX_wds + self.ZSDY_wds + 
            self.ZSDYJX_wds + self.ZSDYNX_wds)

        # 构造领域actree
        self.region_tree = self.build_actree(list(self.region_words))
        # 构建词典
        self.wdtype_dict = self.build_wdtype_dict()

        # 问句疑问词
        # 知识单元
        self.q1_qwds = ['知识单元有哪些','知识单元有啥','知识单元有什么', '知识框架', '知识结构']
        # 介绍
        self.q2_qwds = ['简介', '介绍', '概述']
        # 学时
        self.q3_qwds = ['学时', '课时', '时间']
        # 教学大纲
        self.q4_qwds = ['大纲', '教学大纲', '教学内容']
        # 先修课程
        self.q5_qwds = ['先修内容', '先修课程', '课程基础']
        # 知识点
        self.q6_qwds = ['知识点有哪些', '知识内容', '具体知识']
        # 归属
        self.q7_qwds = ['属于', '归于', '大类']
        # 掌握程度
        self.q8_qwds = ['掌握程度', '要求的掌握程度', '掌握要求']
        # 重要程度
        self.q9_qwds = ['重要程度', '重要性']
        # 后继课程
        self.q10_qwds = ['后继课程', '为什么课程做铺垫','为哪些课程做铺垫']
        # 前置课程
        self.q11_qwds = ['前置课程']
        # 后继知识点
        self.q12_qwds = ['后继知识点', '为什么知识点做铺垫','为哪些知识点做铺垫']
        # 前置知识点
        self.q13_qwds = ['前置知识点']
        # 后继知识单元
        self.q14_qwds = ['后继知识单元', '为什么知识单元做铺垫','为哪些知识单元做铺垫']
        # 前置知识单元
        self.q15_qwds = ['前置知识单元']
        # 知识单元所含知识点
        self.q16_qwds = ['涵盖哪些知识点']
        # 知识单元所属课程
        self.q17_qwds = ['属于什么课程','属于哪些课程']
        # 知识单元数量
        self.q18_qwds = ['多少知识单元','包含多少知识单元','多少个知识单元']
        # 知识点数量
        self.q19_qwds = ['多少知识点','包含多少知识点','多少个知识点']
        print('model init finished ......')

        return

    '''分类主函数'''
    def classify(self, question):
        data = {}
        medical_dict = self.check_medical(question)
        if not medical_dict:
            return {}
        data['args'] = medical_dict
        #收集问句当中所涉及到的实体类型
        types = []
        for type_ in medical_dict.values():
            types += type_
        question_type = 'others'

        question_types = []

        # 知识单元
        if self.check_words(self.q1_qwds, question) and ('kecheng' in types):
            question_type = 'zhishidanyuan'
            question_types.append(question_type)
        # 介绍
        if self.check_words(self.q2_qwds, question) and ('kecheng' in types):
            question_type = 'jieshao'
            question_types.append(question_type)
        # 学时
        if self.check_words(self.q3_qwds, question) and ('kecheng' in types):
            question_type = 'xueshi'
            question_types.append(question_type)
        # 教学大纲
        if self.check_words(self.q4_qwds, question) and ('kecheng' in types):
            question_type = 'dagang'
            question_types.append(question_type)
        # 先修课程
        if self.check_words(self.q5_qwds, question) and ('kecheng' in types):
            question_type = 'xianxiukecheng'
            question_types.append(question_type)
        # 知识点
        if self.check_words(self.q6_qwds, question) and ('kecheng' in types):
            question_type = 'zhishidian'
            question_types.append(question_type)
        # 归属
        if self.check_words(self.q7_qwds, question) and ('kecheng' in types):
            question_type = 'guishu'
            question_types.append(question_type)
        # 掌握程度
        if self.check_words(self.q8_qwds, question) and ('ZSD' in types):
            question_type = 'zhangwochengdu'
            question_types.append(question_type)
        # 重要程度
        if self.check_words(self.q9_qwds, question) and ('ZSD' in types):
            question_type = 'zhongyaochengdu'
            question_types.append(question_type)
        # 后继课程
        if self.check_words(self.q10_qwds, question) and ('kecheng' in types):
            question_type = 'houjikecheng'
            question_types.append(question_type)
        # 前置课程
        if self.check_words(self.q11_qwds, question) and ('kecheng' in types):
            question_type = 'qianzhikecheng'
            question_types.append(question_type)
        # 后继知识点
        if self.check_words(self.q12_qwds, question) and ('ZSD' in types):
            question_type = 'houjizhishidian'
            question_types.append(question_type)
        # 前置知识点
        if self.check_words(self.q13_qwds, question) and ('ZSD' in types):
            question_type = 'qianzhizhishidian'
            question_types.append(question_type)
        # 后继知识单元
        if self.check_words(self.q14_qwds, question) and ('ZSDY' in types):
            question_type = 'houjizhishidanyuan'
            question_types.append(question_type)
        # 前置知识单元
        if self.check_words(self.q15_qwds, question) and ('ZSDY' in types):
            question_type = 'qianzhizhishidanyuan'
            question_types.append(question_type)
        # 知识单元所含知识点
        if self.check_words(self.q16_qwds, question) and ('ZSDY' in types):
            question_type = 'ZSDYZSD'
            question_types.append(question_type)
        # 知识单元所属课程
        if self.check_words(self.q17_qwds, question) and ('ZSDY' in types):
            question_type = 'ZSDYKC'
            question_types.append(question_type)
        # 课程知识单元数量
        if self.check_words(self.q18_qwds, question) and ('kecheng' in types):
            question_type = 'ZSDYSL'
            question_types.append(question_type)
        # 课程知识点数量
        if self.check_words(self.q19_qwds, question) and ('kecheng' in types):
            question_type = 'ZSDSL'
            question_types.append(question_type)
        # 将多个分类结果进行合并处理，组装成一个字典
        data['question_types'] = question_types

        return data

    '''构造词对应的类型'''
    def build_wdtype_dict(self):
        wd_dict = dict()
        for wd in self.region_words:
            wd_dict[wd] = []
            if wd in self.kecheng_wds:
                wd_dict[wd].append('kecheng')
            if wd in self.kechengJX_wds:
                wd_dict[wd].append('kechengJX')
            if wd in self.kechengNX_wds:
                wd_dict[wd].append('kechengNX')
            if wd in self.kechengZSD_wds:
                wd_dict[wd].append('kechengZSD')
            if wd in self.kechengZSDJX_wds:
                wd_dict[wd].append('kechengZSDJX')
            if wd in self.kechengZSDNX_wds:
                wd_dict[wd].append('kechengZSDNX')
            if wd in self.kechengZSDY_wds:
                wd_dict[wd].append('kechengZSDY')
            if wd in self.kechengZSDYJX_wds:
                wd_dict[wd].append('kechengZSDYJX')
            if wd in self.kechengZSDYNX_wds:
                wd_dict[wd].append('kechengZSDYNX')
            if wd in self.xiti_wds:
                wd_dict[wd].append('xiti')
            if wd in self.zhuanye_wds:
                wd_dict[wd].append('zhuanye')
            if wd in self.zhuanyeJX_wds:
                wd_dict[wd].append('zhuanyeJX')
            if wd in self.ZSD_wds:
                wd_dict[wd].append('ZSD')
            if wd in self.ZSDJX_wds:
                wd_dict[wd].append('ZSDJX')
            if wd in self.ZSDNX_wds:
                wd_dict[wd].append('ZSDNX')
            if wd in self.ZSDY_wds:
                wd_dict[wd].append('ZSDY')
            if wd in self.ZSDYJX_wds:
                wd_dict[wd].append('ZSDYJX')
            if wd in self.ZSDYNX_wds:
                wd_dict[wd].append('ZSDYNX')
        return wd_dict

    '''构造actree，加速过滤'''
    def build_actree(self, wordlist):
        actree = ahocorasick.Automaton()
        for index, word in enumerate(wordlist):
            actree.add_word(word, (index, word))
        actree.make_automaton()
        return actree

    '''问句过滤'''
    def check_medical(self, question):
        region_wds = []
        for i in self.region_tree.iter(question):
            wd = i[1][1]
            region_wds.append(wd)
        stop_wds = []
        for wd1 in region_wds:
            for wd2 in region_wds:
                if wd1 in wd2 and wd1 != wd2:
                    stop_wds.append(wd1)
        final_wds = [i for i in region_wds if i not in stop_wds]
        final_dict = {i:self.wdtype_dict.get(i) for i in final_wds}
        if(final_dict):
            # print(final_dict)
            return final_dict
        else:
            # print('空')

            return {'递归': ['ZSD']}

    '''基于特征词进行分类'''
    def check_words(self, wds, sent):
        for wd in wds:
            if wd in sent:
                return True
        return False


if __name__ == '__main__':

    handler = QuestionClassifier()
    while 1:
        question = input('input an question:')
        data = handler.classify(question)
        print(data)
